import { getCompensateEventDefinition, getCompensateActivity } from './bpmnPropertyUtils/eventDefinition'
import { useModelerStore } from '@/store/bpmnProcess/modelerStore'
import { getBusinessObject, is } from 'bpmn-js/lib/util/ModelUtil'
import { find } from 'min-dash'

export function getWaitForCompletionValue(element) {
  const compensateEventDefinition = getCompensateEventDefinition(element)
  return compensateEventDefinition.get('waitForCompletion')
}

export function setWaitForCompletionValue(element, value) {
  const modeling = useModelerStore().getModeling
  const compensateEventDefinition = getCompensateEventDefinition(element)
  modeling.updateModdleProperties(element, compensateEventDefinition, { waitForCompletion: value })
}

export function getActivityRef(element) {
  const activityRef = getCompensateActivity(element)
  return activityRef && activityRef.get('id')
}

export function setActivityRef(element, value) {
  const elementRegistry = useModelerStore().getElRegistry
  const modeling = useModelerStore().getModeling
  const compensateEventDefinition = getCompensateEventDefinition(element)
  const activityRef = value ? getBusinessObject(elementRegistry.get(value)) : undefined
  modeling.updateModdleProperties(element, compensateEventDefinition, { activityRef })
}

export function getActivityOptions(element) {
  const options = []
  const activities = findActivityRefs(element)
  activities.forEach((activity: any) => {
    options.push({
      value: activity.id,
      label: createOptionLabel(activity)
    })
  })
  return options
}

function findActivityRefs(element) {
  const businessObject = getBusinessObject(element)
  let parent = businessObject.$parent

  // (1) get all activities in parent container
  let activities = getActivitiesForCompensation(parent)

  // (2) if throwing compensation event is inside an EventSubProcess,
  // also get all activities outside of the event sub process
  if (is(parent, 'bpmn:SubProcess') && parent.triggeredByEvent) {
    parent = parent.$parent
    if (parent) {
      activities = [...activities, ...getActivitiesForCompensation(parent)]
    }
  }
  return activities
}

function getFlowElements(element, type) {
  const { flowElements } = element
  return flowElements.filter(function (flowElement) {
    return is(flowElement, type)
  })
}

function getContainedActivities(element) {
  return getFlowElements(element, 'bpmn:Activity')
}

function getContainedBoundaryEvents(element) {
  return getFlowElements(element, 'bpmn:BoundaryEvent')
}

function hasCompensationEventAttached(activity, boundaryEvents) {
  const { id: activityId } = activity
  return !!find(boundaryEvents, function (boundaryEvent) {
    const { attachedToRef } = boundaryEvent
    const compensateEventDefinition = getCompensateEventDefinition(boundaryEvent)
    return attachedToRef && compensateEventDefinition && attachedToRef.id === activityId
  })
}

function canBeCompensated(activity, boundaryEvents) {
  return is(activity, 'bpmn:CallActivity') || (is(activity, 'bpmn:SubProcess') && !activity.triggeredByEvent && !activity.isForCompensation) || hasCompensationEventAttached(activity, boundaryEvents)
}

function getActivitiesForCompensation(element) {
  const activities = getContainedActivities(element)
  const boundaryEvents = getContainedBoundaryEvents(element)
  return activities.filter(function (activity) {
    return canBeCompensated(activity, boundaryEvents)
  })
}

function createOptionLabel(activity) {
  const { id, name } = activity
  console.log(activity, '活动项')
  return `${name ? name + ' ' : ''}(id=${id})`
}
